#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "string.h"
#include "comFunction.h"

void OLED_WR_Byte(unsigned dat, unsigned cmd)
{
    if (cmd)
    {
        i2c_start();
        i2c_write_byte(0x78); // D/C#=0; R/W#=0
        i2c_wait_ack();
        i2c_write_byte(0x40); // write data
        i2c_wait_ack();
        i2c_write_byte(dat);
        i2c_wait_ack();
        i2c_stop();
    }
    else
    {
        i2c_start();
        i2c_write_byte(0x78); // Slave address,SA0=0
        i2c_wait_ack();
        i2c_write_byte(0x00); // write command
        i2c_wait_ack();
        i2c_write_byte(dat);
        i2c_wait_ack();
        i2c_stop();
    }
}

// OLED的显存
// 存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
    unsigned char m, n;
    for (m = 0; m < 8; m++)
    {
        OLED_WR_Byte(0xb0 + m, 0); // page0-page1
        OLED_WR_Byte(0x00, 0);     // low column start address
        OLED_WR_Byte(0x10, 0);     // high column start address
        for (n = 0; n < 128; n++)
        {
            OLED_WR_Byte(fill_Data, 1);
        }
    }
}

// 坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
// 开启OLED显示
void OLED_Display_On(void)
{
    OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
    OLED_WR_Byte(0X14, OLED_CMD); // DCDC ON
    OLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}
// 关闭OLED显示
void OLED_Display_Off(void)
{
    OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
    OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFF
    OLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}
// 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); // 设置页地址（0~7）
        OLED_WR_Byte(0x00, OLED_CMD);     // 设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD);     // 设置显示位置—列高地址
        for (n = 0; n < 128; n++)
            OLED_WR_Byte(0, OLED_DATA);
    } // 更新显示
}
void OLED_On(void)
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); // 设置页地址（0~7）
        OLED_WR_Byte(0x00, OLED_CMD);     // 设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD);     // 设置显示位置—列高地址
        for (n = 0; n < 128; n++)
            OLED_WR_Byte(1, OLED_DATA);
    } // 更新显示
}
// 在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// mode:0,反白显示;1,正常显示
// size:选择字体 16/12
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr)
{
    unsigned char c = 0, i = 0;
    c = chr - ' '; // 得到偏移后的值
    if (x > Max_Column - 1)
    {
        x = 0;
        y = y + 2;
    }

    OLED_Set_Pos(x, y);
    for (i = 0; i < 6; i++)
        OLED_WR_Byte(F6x8[c][i], OLED_DATA);

}

/**
 * @brief 显示字符串，自动回车
 *
 * @param x
 * @param y
 * @param chr
 * @param len
 */
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *chr, unsigned char len)
{
    unsigned char j = 0;
    while (chr[j] != '\0' && len--)
    {
        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if (x > Max_Column - 8)
        {
            x = 0;
            y ++;
        }
        j++;
    }
}

/**
 * @brief OLED显示有符号数字，实际上是先将数字转换为字符串，再显示字符串
 *
 * @param x
 * @param y
 * @param num 需要显示的数字
 * @param len 需要显示的长度，注意，符号也占一位
 */
void OLED_ShowInt(unsigned char x, unsigned char y, long num, unsigned char len)
{
    unsigned char i = 0;
    unsigned char m = ' ';
    if (num < 0)
    {
        m = '-';
        num = -num;
    }
    len--; // 少一位放符号
    for (i; i < len; i++) // 预先到终点，逆序，少一次
    {
        x += 8;
        if (x > Max_Column - 8)
        {
            x = 0;
            y++;
        }
    }

    while (len--)
    {
        OLED_ShowChar(x, y, num % 10 + '0');
        num /= 10;
        x -= 8;
        if (x < 0)
        {
            x = Max_Column - 8;
            y--;
        }
    }
    OLED_ShowChar(x, y, m);
}

/**
 * @brief OLED显示无符号数字，实际上是先将数字转换为字符串，再显示字符串
 *
 * @param x
 * @param y
 * @param num 需要显示的数字
 * @param len 需要显示的长度
 */
void OLED_ShowUInt(unsigned char x, unsigned char y, long num, unsigned char len)
{
    unsigned char i = 0;
    for (i ; i < len - 1; i++) // 预先到终点，逆序，少一次
    {
        x += 8;
        if (x > Max_Column - 8)
        {
            x = 0;
            y++;
        }
    }

    while (len--)
    {
        OLED_ShowChar(x, y, num % 10 + '0');
        num /= 10;
        x -= 8;
        if (x < 0)
        {
            x = Max_Column - 8;
            y--;
        }
    }
}

/***********功能描述：显示显示BMP图片128×64起始点坐标(x,y),x的范围0～127，y为页的范围0～7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[])
{
    unsigned int j = 0;
    unsigned char x, y;

    if (y1 % 8 == 0)
        y = y1 / 8;
    else
        y = y1 / 8 + 1;
    for (y = y0; y < y1; y++)
    {
        OLED_Set_Pos(x0, y);
        for (x = x0; x < x1; x++)
        {
            OLED_WR_Byte(BMP[j++], OLED_DATA);
        }
    }
}

// 初始化SSD1306
void OLED_Init(void)
{

    OLED_WR_Byte(0xAE, OLED_CMD); //--display off
    OLED_WR_Byte(0x00, OLED_CMD); //---set low column address
    OLED_WR_Byte(0x10, OLED_CMD); //---set high column address
    OLED_WR_Byte(0x40, OLED_CMD); //--set start line address
    OLED_WR_Byte(0xB0, OLED_CMD); //--set page address
    OLED_WR_Byte(0x81, OLED_CMD); // contract control
    OLED_WR_Byte(0xFF, OLED_CMD); //--128
    OLED_WR_Byte(0xA1, OLED_CMD); // set segment remap
    OLED_WR_Byte(0xA6, OLED_CMD); //--normal / reverse
    OLED_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3F, OLED_CMD); //--1/32 duty
    OLED_WR_Byte(0xC8, OLED_CMD); // Com scan direction
    OLED_WR_Byte(0xD3, OLED_CMD); //-set display offset
    OLED_WR_Byte(0x00, OLED_CMD); //

    OLED_WR_Byte(0xD5, OLED_CMD); // set osc division
    OLED_WR_Byte(0x80, OLED_CMD); //

    OLED_WR_Byte(0xD8, OLED_CMD); // set area color mode off
    OLED_WR_Byte(0x05, OLED_CMD); //

    OLED_WR_Byte(0xD9, OLED_CMD); // Set Pre-Charge Period
    OLED_WR_Byte(0xF1, OLED_CMD); //

    OLED_WR_Byte(0xDA, OLED_CMD); // set com pin configuartion
    OLED_WR_Byte(0x12, OLED_CMD); //

    OLED_WR_Byte(0xDB, OLED_CMD); // set Vcomh
    OLED_WR_Byte(0x30, OLED_CMD); //

    OLED_WR_Byte(0x8D, OLED_CMD); // set charge pump enable
    OLED_WR_Byte(0x14, OLED_CMD); //

    OLED_WR_Byte(0xAF, OLED_CMD); //--turn on oled panel

    OLED_Clear();
}
